Handle missing files after `cargo rustc`
authorAlex Crichton <alex@alexcrichton.com>
Wed, 10 Jun 2015 01:40:50 +0000 (18:40 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 10 Jun 2015 01:40:50 +0000 (18:40 -0700)
Some flags to the compiler could cause it to stop early or not emit some files
altogether (or perhaps emit files in different locations even). Currently cargo
expects a few outputs of the compiler after `cargo rustc` is run, but this
commit alters cargo to know that when `cargo rustc` is being run that the
outputs may not exist and that's ok.

Closes #1675

src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_compile.rs

index 05e5ddd1af310abecef39d3c378dde0994a4975a..b72931d19bb75784c95600dae3ed1dd874156d99 100644 (file)
@@ -66,7 +66,8 @@ pub fn prepare_target<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
         }
     }
 
-    Ok(prepare(is_fresh && !missing_outputs, loc, fingerprint))
+    let allow_failure = profile.rustc_args.is_some();
+    Ok(prepare(is_fresh && !missing_outputs, allow_failure, loc, fingerprint))
 }
 
 /// A fingerprint can be considered to be a "short string" representing the
@@ -256,7 +257,7 @@ pub fn prepare_build_cmd(cx: &mut Context, pkg: &Package, kind: Kind)
 
     let is_fresh = try!(is_fresh(&loc, &new_fingerprint));
 
-    Ok(prepare(is_fresh, loc, new_fingerprint))
+    Ok(prepare(is_fresh, false, loc, new_fingerprint))
 }
 
 /// Prepare work for when a package starts to build
@@ -284,13 +285,19 @@ pub fn prepare_init(cx: &mut Context, pkg: &Package, kind: Kind)
 /// Given the data to build and write a fingerprint, generate some Work
 /// instances to actually perform the necessary work.
 fn prepare(is_fresh: bool,
+           allow_failure: bool,
            loc: PathBuf,
            fingerprint: Fingerprint) -> Preparation {
     let write_fingerprint = Work::new(move |_| {
         debug!("write fingerprint: {}", loc.display());
-        let fingerprint = try!(fingerprint.resolve(true).chain_error(|| {
+        let fingerprint = fingerprint.resolve(true).chain_error(|| {
             internal("failed to resolve a pending fingerprint")
-        }));
+        });
+        let fingerprint = match fingerprint {
+            Ok(f) => f,
+            Err(..) if allow_failure => return Ok(()),
+            Err(e) => return Err(e),
+        };
         let mut f = try!(File::create(&loc));
         try!(f.write_all(fingerprint.as_bytes()));
         Ok(())
index 162930be9a565f77378e60320fe3ec4c68c21644..44b4f1adba91ec956724549e097bc5578abd9342 100644 (file)
@@ -341,6 +341,7 @@ fn rustc(package: &Package, target: &Target, profile: &Profile,
         if !show_warnings {
             rustc.arg("-Awarnings");
         }
+        let has_custom_args = profile.rustc_args.is_some();
         let exec_engine = cx.exec_engine.clone();
 
         let filenames = try!(cx.target_filenames(package, target, profile,
@@ -407,16 +408,20 @@ fn rustc(package: &Package, target: &Target, profile: &Profile,
                 let src = dst.with_file_name(dst.file_name().unwrap()
                                                 .to_str().unwrap()
                                                 .replace(&real_name, &crate_name));
-                try!(fs::rename(&src, &dst).chain_error(|| {
-                    internal(format!("could not rename crate {:?}", src))
-                }));
+                if !has_custom_args || fs::metadata(&src).is_ok() {
+                    try!(fs::rename(&src, &dst).chain_error(|| {
+                        internal(format!("could not rename crate {:?}", src))
+                    }));
+                }
             }
 
-            try!(fs::rename(&rustc_dep_info_loc, &dep_info_loc).chain_error(|| {
-                internal(format!("could not rename dep info: {:?}",
-                              rustc_dep_info_loc))
-            }));
-            try!(fingerprint::append_current_dir(&dep_info_loc, &cwd));
+            if !has_custom_args || fs::metadata(&rustc_dep_info_loc).is_ok() {
+                try!(fs::rename(&rustc_dep_info_loc, &dep_info_loc).chain_error(|| {
+                    internal(format!("could not rename dep info: {:?}",
+                                  rustc_dep_info_loc))
+                }));
+                try!(fingerprint::append_current_dir(&dep_info_loc, &cwd));
+            }
 
             Ok(())
 
index 448531d676aad31fc77e4585dd0fbd49aec64e2b..02cfa26649f0dc9f67333f604dba695a1731e97e 100644 (file)
@@ -1886,3 +1886,18 @@ test!(custom_target_dir {
     assert_that(&p.root().join("target/debug").join(&exe_name),
                 existing_file());
 });
+
+test!(rustc_no_trans {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+        "#)
+        .file("src/main.rs", "fn main() {}");
+    p.build();
+
+    assert_that(p.cargo("rustc").arg("-v").arg("--").arg("-Zno-trans"),
+                execs().with_status(0));
+});